package com.alander.nexusgo.framework.file.starter.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.alander.nexusgo.framework.file.starter.model.File;
import com.alander.nexusgo.framework.file.starter.model.OssProperties;
import com.alander.nexusgo.framework.file.starter.service.FileService;
import com.alander.nexusgo.framework.file.starter.service.FileUploadService;
import com.alander.nexusgo.framework.file.starter.utils.FileUtils;
import com.aliyun.oss.OSS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
public class OssFileUploadService implements FileUploadService {

    private final OSS ossClient;
    private final OssProperties ossProperties;

    public OssFileUploadService(OSS ossClient, OssProperties ossProperties) {
        this.ossClient = ossClient;
        this.ossProperties = ossProperties;
    }

    @Resource
    private FileService fileService;

    @Resource
    private FileUtils fileUtils;

    @Override
    public String uploadFile(MultipartFile file) throws IOException {
        return doUploadFile(file, null);
    }

    @Override
    public String uploadFile(MultipartFile file, String preFilePath) throws IOException {
        return doUploadFile(file, preFilePath);
    }

    @Override
    public List<String> uploadFiles(List<MultipartFile> files) throws IOException {
        List<String> fileUrls = new ArrayList<>();
        for (MultipartFile file : files) {
            String url = uploadFile(file);
            fileUrls.add(url);
        }
        return fileUrls;
    }

    @Override
    public List<String> uploadFiles(List<MultipartFile> files, String preFilePath) throws IOException {
        List<String> fileUrls = new ArrayList<>();
        for (MultipartFile file : files) {
            String url = uploadFile(file, preFilePath);
            fileUrls.add(url);
        }
        return fileUrls;
    }

    private String doUploadFile(MultipartFile file, String preFilePath) throws IOException {
        fileUtils.validateFile(file); // 安全校验

        // 计算文件MD5
        String fileMd5 = fileUtils.calculateFileMd5(file);

        // 检查是否已存在相同文件
        File existingFile = fileService.getOne(new LambdaQueryWrapper<File>()
                .eq(File::getFileMd5, fileMd5)
                .eq(File::getDelFlag, "0"));

        if (existingFile != null) {
            // 文件已存在，直接返回已存在的URL
            return existingFile.getFileUrl();
        }

        String storedFileName = fileUtils.generateFileName(file.getOriginalFilename(),preFilePath);
        String originalFileName = file.getOriginalFilename();

        Long userId = StpUtil.getLoginIdAsLong();
        LocalDateTime now = LocalDateTime.now();

        String fileUrl;

        try (InputStream inputStream = file.getInputStream()) {
            // 上传到OSS
            ossClient.putObject(ossProperties.getBucketName(), storedFileName, inputStream);

            // 构建文件访问URL
            if (StringUtils.hasText(ossProperties.getDomain())) {
                String domain = fileUtils.ensureProtocol(ossProperties.getDomain());
                fileUrl = domain + (preFilePath != null ? "/" + preFilePath : "") + storedFileName;
            } else {
                String protocol = ossProperties.isUseHttps() ? "https://" : "http://";
                fileUrl = protocol + ossProperties.getBucketName() + "." + ossProperties.getEndpoint() + "/" + storedFileName;
            }

            // 保存文件信息到数据库
            File fileEntity = File.builder()
                    .userId(userId)
                    .fileName(originalFileName)
                    .fileUrl(fileUrl)
                    .filePath(storedFileName)
                    .fileSize(file.getSize())
                    .fileType(file.getContentType())
                    .fileMd5(fileMd5)
                    .createBy(String.valueOf(userId))
                    .createTime(now)
                    .updateBy(String.valueOf(userId))
                    .updateTime(now)
                    .build();

            try {
                fileService.save(fileEntity);
            } catch (Exception e) {
                // 回滚：删除已上传的OSS文件
                ossClient.deleteObject(ossProperties.getBucketName(), storedFileName);
                throw e;
            }

        }

        return fileUrl;
    }

    @Override
    public void deleteFile(String fileName) {
        //ossClient.deleteObject(ossProperties.getBucketName(), fileName);
        // 调用 fileService 删除对应的数据库记录
        LambdaUpdateWrapper<File> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(File::getFilePath, fileName)
                .set(File::getDelFlag, "1");
        fileService.update(updateWrapper);
    }


}


